﻿namespace Nomo.UnityCoreModule
{
    /// <summary>
    /// 为需要使用单一实例模式的继承自 <see cref="UnityEngine.MonoBehaviour"/> 的类提供基类。
    /// </summary>
    /// <typeparam name="T">需要使用单一实例模式的继承自 <see cref="UnityEngine.MonoBehaviour"/> 的类的类型。</typeparam>
    [UnityEngine.DisallowMultipleComponent]
    public abstract class SingletonBehaviour<T> : UnityEngine.MonoBehaviour where T : UnityEngine.MonoBehaviour
    {
        private const UnityEngine.HideFlags HideFlags = UnityEngine.HideFlags.HideInHierarchy | UnityEngine.HideFlags.HideInInspector;

        static SingletonBehaviour()
        {
            if (!typeof(T).IsSealed)
            {
                throw new System.NotSupportedException("类必须密封。");
            }
        }

        private static T _instance;

        /// <summary>
        /// 获取 <typeparamref name="T"/> 的单一实例。
        /// </summary>
        public static T Instance => _instance != null ? _instance : (_instance = FindInstance()) != null ? _instance : _instance = CreateInstance();

        private static T FindInstance()
        {
            var instance = FindObjectOfType<T>();
            if (instance != default)
            {
                var gameObject = instance.gameObject;
                gameObject.hideFlags |= HideFlags;
                DontDestroyOnLoad(gameObject);
            }
            return instance;
        }

        private static T CreateInstance()
        {
            var gameObject = new UnityEngine.GameObject(typeof(T).Name);
            var instance   = gameObject.AddComponent<T>();
            gameObject.hideFlags |= HideFlags;
            DontDestroyOnLoad(gameObject);
            return instance;
        }
    }
}
